#include <assert.h>
#include "Session.h"
#include <sys/timeb.h>
#include "logging.h"
typedef struct {
	uv_write_t req;
	uv_buf_t buf;
} write_req_t;



Session::Session(uv_stream_t*streamm) :_streamm(streamm)
{
	struct timeb t;
	ftime(&t);
	id = (unsigned long long)this;			
}


Session::~Session()
{
	trace("~Session()\n");		
}
void Session::_AllocBuf(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf)
{
	Session* session = (Session*)handle->data;
	buf->base = session->_rbuf._base;
	buf->len = session->_rbuf._size;
}

void Session::CloseSession()
{		
	if (0 == uv_is_closing((uv_handle_t*)_streamm)){					
		_streamm->data = this;						
		uv_close((uv_handle_t*)_streamm, Session::_OnCloseCb);
	}		
}

void Session::OnRead(SessionReadCb sReadcb)
{	
	assert(_streamm);
	_sReadcb = sReadcb;
	_streamm->data = this;
	uv_read_start(_streamm, Session::_AllocBuf, Session::_OnReadCb);
}


void Session::Write(char* buf, size_t bsize)
{			
	write_req_t *req = (write_req_t*)malloc(sizeof(write_req_t));	
	req->buf = uv_buf_init(buf, bsize);
	uv_write((uv_write_t*)req, _streamm, &req->buf, 1, Session::_OnWriteCb);
}

void Session::_OnReadCb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf)
{	
	Session* session = (Session*)handle->data;	
	if (nread < 0){		
		uv_close((uv_handle_t*)handle, Session::_OnCloseCb);
		return;
	}
	assert(session->_sReadcb);
	session->_sReadcb(session->shared_from_this(), buf->base, nread);
}

void Session::_OnWriteCb(uv_write_t* req, int status)
{			
	uv_read_start(req->handle, Session::_AllocBuf, Session::_OnReadCb);			
	free(req);
}
void Session::_OnCloseCb(uv_handle_t* handle)
{
	Session* session = (Session*)handle->data;
	if (session->_sClosecb)
	{
		trace("session on close\n");
		session->_sClosecb(session->shared_from_this());
	}		
	if (!session->m_bClient)
	{
		trace("session free handle\n");
		free(handle);
	}		
}